
/**
发送任务
 *
*/
import { ActionArgHelper } from "GameLoop/Execution/ControlManager/Control/ActionManager/ActionArgHelper";
import { CoreEntity } from "GameLoop/WorldState/EntityManager/Entitys";
import { State } from "framework/FSM/AState";
import { priority } from "utils/constants/definetypes";

export class TerminalTask<T extends IStateArg<Room >> extends State<T>
{
    public getActions(arg:T):Action[]
    {
        const dealTask = arg.entity.getTaskByType("terminal")[0] ;
        const coreEntity = arg.entity.getEntity("CoreEntity");
       
        if(!dealTask)
        {
            return []
        }
        switch(dealTask.data.type)
        {
            case "send":
                return this.getSendAction(coreEntity,dealTask as ITask<ITerminalTaskData<"send">>);
            case "buy":
                return  [ActionArgHelper.actionTerminalDeal(arg.entity,
                    _.assign({taskid:dealTask.id},dealTask.data.arg) as IDealTask,"dealbuy")]
            case "sell":
                return  [ActionArgHelper.actionTerminalDeal(arg.entity,
                    _.assign({taskid:dealTask.id},dealTask.data.arg) as IDealTask,"dealsell")]
        }
        // return []
    }
    private getSendAction(coreentity:CoreEntity,arg:ITask<ITerminalTaskData<"send">>):Action[]
    {
        
        
        if(!arg.data.arg.replenish || !arg.data.arg.replenish.transport)
        {
            // 更新填充参数
            let replenish:IReplenish|undefined     // 需要填充的信息
            let transportkey:string|false|0=false;
            // 可以发送了。1.仓库接近满了。且没有转移任务 2.资源已经够了。且没有转移任务
            if(arg.data.arg.Resource.resourceType == RESOURCE_ENERGY)
            {
                replenish = this.getEnergyReplenish(coreentity,arg.data.arg);
                if(replenish.fee+replenish.resource>0)
                {
                    transportkey = this.replenishTerminal(coreentity,[{resourceType:RESOURCE_ENERGY,amount:replenish.fee+replenish.resource}]);
                }
            }
            else
            {
                replenish =  this.getResourceReplenish(coreentity,arg.data.arg);
                const transfportItem:Required<IResource>[]=[];
                if(replenish.resource>0)
                {
                    transfportItem.push(   {
                        resourceType:arg.data.arg.Resource.resourceType,amount:replenish.resource})
                }
                if(replenish.fee>0)
                {
                    transfportItem.push(     {
                        resourceType:RESOURCE_ENERGY,amount:replenish.fee})
                }
                if(transfportItem.length>0)
                {
                    transportkey = this.replenishTerminal(coreentity,transfportItem);
                }
                
            }
            // 投递转移任务
            if(transportkey)
            {
                arg.data.arg.replenish = replenish as any;
                (arg.data.arg.replenish as any).transport=transportkey;
            }
            else
            {
                // 
                coreentity.log("info","不需要填充资源","直接发送",JSON.stringify(replenish))
            }
        }
  
        if(arg.data.arg.replenish  )
        {
          
            // 等待填充然后发送
            let isTransfering = coreentity.isTransfering(arg.data.arg.replenish.transport);
            if(!isTransfering || coreentity.Terminal.store.getFreeCapacity()==0)
            {
                // 终端满了。或者不在运输中。就可以发送了

                const code = coreentity.Terminal.send(arg.data.arg.Resource.resourceType,arg.data.arg.replenish.sendAmount,arg.data.arg.To);
                if(code == OK)
                {
                    arg.data.arg.Resource.amount-=arg.data.arg.replenish.sendAmount
                  
                }
                else 
                {
                    coreentity.log("error",`资源发送错误 ${code} 手动删除发送任务 [Game.rooms['${coreentity.room.name}'].deleteTaskById('${arg.id}') ]`);
                    if(arg.data.arg.Resource.amount>0)
                    {
                        coreentity.room.tryDelayTaskById(arg.id);
                    }
                    
                }
                if( arg.data.arg.Resource.amount<=0)
                {
                    // 任务完成
                    coreentity.room.deleteTaskById(arg.id,"terminal");
                    if(arg.data.arg.replenish.transport)
                    {
                        coreentity.room.deleteTaskById(arg.data.arg.replenish.transport,"core")
                    }
                    
                }
                if(!isTransfering)
                {
                    arg.data.arg.replenish= undefined;  // 发送完成后填充任务置空
                }
            }
        }
        else  
        {
            // 不需要填充资源
            if( arg.data.arg.Resource.amount<=0)
            {
                coreentity.room.deleteTaskById(arg.id,"terminal");
            }
            else
            {
                const code = coreentity.Terminal.send(arg.data.arg.Resource.resourceType,arg.data.arg.Resource.amount,arg.data.arg.To);
                if(code == OK)
                {
                    coreentity.room.deleteTaskById(arg.id,"terminal");
                }
                else 
                {
                    coreentity.log("error",`${arg.data.arg.Resource.resourceType}:[${arg.data.arg.Resource.amount}] ->${arg.data.arg.To} 资源发送错误 ${code} 手动删除发送任务 [Game.rooms['${coreentity.room.name}'].deleteTaskById('${arg.id}') ]`);
                    // coreentity.room.deleteTaskById(arg.id);
                }
            }
        }
      
        return []
    }
    /**
     * 当要传送的资源是能量时
     * @param coreentity 
     * @param arg 
     * @returns 返回需要填充的资源数量和路费数量
     */
    private getEnergyReplenish(coreentity:CoreEntity,arg:ISendTask):IReplenish
    {
        const freespace = coreentity.Terminal.store.getFreeCapacity();
 
        const existAmountOfEnergy = coreentity.Terminal.store.getUsedCapacity(RESOURCE_ENERGY);
        const transfer_cost = Game.market.calcTransactionCost(arg.Resource.amount,arg.From,arg.To); // 路费需要的数量

        // 需要的总空闲空间
        const space_need = transfer_cost+(arg.Resource.amount-existAmountOfEnergy);
        // 
        if(space_need<=freespace)
        {
            // 终端能够放得下
            return {
                resource:arg.Resource.amount-existAmountOfEnergy,
                fee:transfer_cost,
                sendAmount:arg.Resource.amount
            }
        }
        else
        {
            // 资源占比
            const radio = arg.Resource.amount/(arg.Resource.amount+transfer_cost);
            const energy_max = freespace+existAmountOfEnergy;
          
            // 
            return {
                resource:Math.floor( energy_max *radio),
                fee:energy_max - Math.floor( energy_max *radio),
                sendAmount:Math.floor( energy_max *radio)
            }
        }
    }
    /**
     * 获取填充的资源数量,除energy之外的
     * @param coreentity 
     * @param arg 
     * @returns 
     */
    private getResourceReplenish(coreentity:CoreEntity,arg:ISendTask):IReplenish
    {
        const freespace = coreentity.Terminal.store.getFreeCapacity();
        const existAmountOfResource = coreentity.Terminal.store.getUsedCapacity(arg.Resource.resourceType);
        const existAmountOfEnergy = coreentity.Terminal.store.getUsedCapacity(RESOURCE_ENERGY);
        const transfer_cost = Game.market.calcTransactionCost(arg.Resource.amount,arg.From,arg.To); // 路费需要的数量

        // 需要的总空闲空间
        const space_need = transfer_cost+(arg.Resource.amount-existAmountOfResource);
        // 
        if(space_need<=freespace)
        {
            // 终端能够放得下
            return {
                resource:arg.Resource.amount-existAmountOfResource,
                fee:transfer_cost-existAmountOfEnergy,
                sendAmount:arg.Resource.amount
            }
        }
        else
        {
            // 资源占比
            const radio = arg.Resource.amount/(arg.Resource.amount+transfer_cost);
            const leftamount = space_need-freespace;
            const left_resource = Math.ceil( leftamount*radio);
            const left_energy = Math.ceil( leftamount*(1-radio));

            // 
            const resource_amount = arg.Resource.amount-existAmountOfResource-left_resource;
            // 除去资源之外剩余空间全部放路费
            return {
                resource:resource_amount,
                fee:freespace-resource_amount,
                sendAmount:existAmountOfResource+resource_amount
            }

        }
    }
    /**
     * 填充资源填充 从storage 到 terminal
     */
    private replenishTerminal(coreentity:CoreEntity,resource:Required<IResource>[])
    {
        // 正在填充的时候不执行
        // const taskId="replenish";
        // 如果任务以及存在了就返回成功
        return coreentity.transferResource(coreentity.Storage as StructureStorage,coreentity.Terminal as StructureTerminal,resource,priority.SSS);
        // return true;
    }
}
